/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#ifndef INCLUDE_BASIC_VEC
#define INCLUDE_BASIC_VEC

#include "basic_def.h"


typedef struct _ui32 {	
	uint32 x, y;		
}ui2_32, uvec2;			

typedef struct _i32_2 { 
	int32 x, y;         
}ivec2;


typedef struct _Vec3 {  
	float32 x, y, z;    
} vec3;					

typedef struct {				
	float32 x; float32 y;		
}vec2;								

//struct vec2 {
//	float32 x; float32 y;
//
//	Inline vec2() {}
//	Inline vec2(float32 _x) :x(_x), y(_x) {}
//	Inline vec2(float32 _x, float32 _y):x(_x), y(_y){}
//};

typedef struct _Vec4 {							
	float32 x; float32 y; float32 z; float32 w;	
}vec4;	

typedef struct _i32_3 {
	int32 x, y, z;
}ivec3;

typedef struct _ui3_32 {			
	uint32 x; uint32 y; uint32 z;	
}uvec3;

typedef struct _ivec4_32 {
	int32 x, y, z, w;
}ivec4;

typedef struct _ui4_32 {					
	uint32 x; uint32 y; uint32 z; uint32 w;	
}uvec4;

typedef struct _ui4_64 {
	uint64 x, y, z, w;
}uvec4_64;

typedef struct {
	int8 x, y;
}bvec2;
typedef struct {
	uint8 x, y;
}ubvec2;
typedef struct {
	uint8 x, y, z;
}ubvec3;

typedef struct {
	int8 x, y, z, w;
}bvec4;

typedef struct _uivec4_8 {
	uint8 x; uint8 y; uint8 z; uint8 w;
}ub4, ubvec4;

typedef struct _ui16 {
	uint16 x; uint16 y;
}ui2_16, suvec2;
typedef struct _i2_16 {
	int16 x; int16 y;
}i2_16, svec2;

typedef struct {
	uint8 x; uint8 y; uint8 z; uint8 w;
}uvec4_8;

typedef struct _ui32_4 {
	uint32 x; uint32 y; uint32 z; uint32 w;
}ui32_4;

typedef struct _i3_16 {
	int16 x, y, z;
}svec3;
typedef struct _i4_16 {
	int16 x, y, z, w;
}svec4;
typedef struct _ui4_16 {
	uint16 x, y, z, w;
}usvec4;






Inline vec2 vec_3to2(const vec3& vec) {
	return { vec.x, vec.y };
}
Inline vec2 vec_4to2(const vec4& vec) {
	return { vec.x, vec.y };
}

Inline vec2 _Vec2(const ivec2& vec) {
	return { float32(vec.x), float32(vec.y) };
}
Inline vec2 _Vec2(const ivec3& vec) {
	return { float32(vec.x), float32(vec.y) };
}
Inline vec2 _Vec2(const ivec4& vec) {
	return { float32(vec.x), float32(vec.y) };
}
Inline vec2 _Vec2(const vec3& vec) {
	return { vec.x, vec.y };
}
Inline vec2 _Vec2(const vec4& vec) {
	return { vec.x, vec.y };
}
Inline ivec2 _iVec2(const vec2& vec) {
	return { int32(vec.x), int32(vec.y) };
}
Inline uvec2 _uVec2(const vec2& vec) {
	return { uint32(vec.x), uint32(vec.y) };
}



Inline vec2 operator+(const vec2& a, const float32 b) {
	return { a.x + b, a.y + b };
};
Inline vec2 operator+(const vec2& a, const vec2& b) {
	return { a.x + b.x, a.y + b.y };
};

Inline vec2 operator*(const vec2& a, const float32 b) {
	return { a.x * b, a.y * b };
};

Inline vec2 operator*(const vec2& a, const vec2& b) {
	return { a.x * b.x, a.y * b.y };
};

Inline vec2 operator-(const vec2& a, const vec2& b) {
	return { a.x - b.x, a.y - b.y };
};
Inline vec2 operator-(const vec2& a, const float32 b) {
	return { a.x - b, a.y - b };
};

Inline vec2 operator/(const vec2& a, const vec2& b) {
	return { a.x / b.x, a.y / b.y };
};

Inline vec2 operator/(const vec2& a, const float32 b) {
	return { a.x / b, a.y / b };
};

Inline void operator/=(vec2& a, const uvec2& b) {
	a.x /= b.x; a.y /= b.y;
};

Inline vec2 operator/(const vec2& a, const uvec2& b) {
	return { a.x / b.x, a.y / b.y };
};

Inline void operator+=(uvec2& a, uint32 b) {
	a.x += b; a.y += b;
};


Inline void operator+=(vec2& a, const float32 b) {
	a.x += b; a.y += b;
};
Inline void operator+=(vec2& a, const vec2& b) {
	a.x += b.x; a.y += b.y;
};
Inline void operator-=(vec2& a, const float32& b) {
	a.x -= b; a.y -= b;
};
Inline void operator-=(vec2& a, const vec2& b) {
	a.x -= b.x; a.y -= b.y;
};
Inline void operator*=(vec2& a, const vec2& b) {
	a.x *= b.x; a.y *= b.y;
};
Inline void operator/=(vec2& a, const float32 b) {
	a.x /= b; a.y /= b;
};
Inline void operator/=(vec2& a, const vec2& b) {
	a.x /= b.x; a.y /= b.y;
};

Inline vec2 operator-(const vec2& a) {
	return { -a.x, -a.y };
};





Inline vec3 operator-(const vec3& a, const float32& b) {
	return { a.x - b, a.y - b, a.z - b };
};

Inline vec3 operator-(const vec3& a, const vec3& b) {
	return { a.x - b.x, a.y - b.y, a.z - b.z };
};

Inline vec3 operator+(const vec3& a, const float32& b) {
	return { a.x + b, a.y + b, a.z + b };
};

Inline vec3 operator+(const vec3& a, const vec3& b) {
	return { a.x + b.x, a.y + b.y, a.z + b.z };
};

Inline vec3 operator*(const vec3& a, const float32& b) {
	return { a.x * b, a.y * b, a.z * b };
};

Inline vec3 operator*(const vec3& a, const vec3& b) {
	return { a.x * b.x, a.y * b.y, a.z * b.z };
};

Inline vec3 operator-(const float32 a, const vec3& b) {
	return { a - b.x, a - b.y, a - b.z };
};

Inline void operator*=(vec3& a, const vec3& b) {
	a.x *= b.x; a.x *= b.y; a.z *= b.z;;
};

Inline void operator*=(vec3& a, const float32& b) {
	a.x *= b; a.y *= b; a.z *= b;
};

Inline vec3 operator/(const vec3& a, const uvec3& b) {
	return { a.x / b.x, a.y / b.y, a.z / b.z };
};

Inline void operator/=(vec3& a, const uvec3& b) {
	a.x /= b.x; a.y /= b.y; a.z /= b.z;
};

Inline void operator+=(vec3& a, const vec3& b) {
	a.x += b.x; a.y += b.y; a.z += b.z;
}

Inline void operator-=(vec3& a, const vec3& b) {
	a.x -= b.x; a.y -= b.y; a.z -= b.z;
}


Inline uvec2 max(const uvec2& a, const uvec2& b) {
	return { a.x > b.x ? a.x : b.x, a.y > b.y ? a.y : b.y };
};

Inline uint32 max(const uvec2& a) {
	return a.x > a.y ? a.x : a.y;
};

Inline uvec2 operator+(uvec2& a, const uint32 b) {
	return {a.x + b, a.y + b};
};

Inline uvec2 operator+(uvec2& a, const uvec2& b) {
	return {a.x + b.x, a.y + b.y};
};

/*Inline vec3 normalize(const vec3& vec) {
	float len = (float)vec_len(vec) + 1e-7;
	if (len) {
		return { vec.x / len, vec.y / len, vec.z / len };
	}
	else return {};
}*/


Inline ivec3 operator + (const ivec3& a, const ivec3& b) {
	return { a.x + b.x, a.y + b.y, a.z + b.z };
};

Inline bool operator == (const ivec3& a, const ivec3& b) {
	return  a.x == b.x && a.y == b.y && a.z == b.z ;
};

Inline bool operator != (const ivec3& a, const ivec3& b) {
	return  a.x != b.x || a.y != b.y || a.z != b.z;
};

Inline ivec3 operator - (const ivec3& a, const int32 b) {
	return { a.x - b, a.y - b, a.z - b };
};




Inline uvec2 operator+(const uvec2& a, const uvec2 b) {
	return { a.x + b.y, a.y + b.y };
};




Inline uvec3 operator+(const uvec3& a, const float32& b) {
	return { uint32(a.x + b), uint32(a.y + b), uint32(a.z + b) };
};

Inline vec3 operator+(const uvec3& a, const vec3& b) {
	return { a.x + b.x, a.y + b.y, a.z + b.z };
};

Inline uvec3 operator+(const uvec3& a, const uint32 b) {
	return { a.x + b, a.y + b, a.z + b };
};

Inline void operator+=(uvec3& a, const float32& b) {
	a.x += b; a.y += b; a.z += b;
};





Inline vec3 operator-(const vec3& a) {
	return {-a.x, -a.y, -a.z};
};






Inline float32 clamp(float32 x, float32 minVal, float32 maxVal) {
	return DEF_Min(DEF_Max(x, minVal), maxVal);
}


Inline float32 mix(const float32& x, const float32& y, const float a) {
	return x * (1.0f - a) + y * a;
}

Inline vec2 mix(const vec2& x, const vec2& y, const float a) {
	return { x.x * (1.0f - a) + y.x * a,
		x.y * (1.0f - a) + y.y * a,
	};
}

Inline vec3 mix(const vec3& x, const vec3& y, const float a) {
	return { x.x * (1.0f - a) + y.x * a,
			 x.y * (1.0f - a) + y.y * a,
			 x.z * (1.0f - a) + y.z * a,
	};
}








typedef struct {
	vec3 pos;
	float32 radius;
}S_VecSphere;


typedef struct {
	vec3 dir;
	float32 w;
}S_Quat;



//=============================================== 矩阵 ====================================================
typedef struct {
	vec2 m0, m1;
}mat2;

typedef struct {
	vec2 m0, m1, m2, m3;
}mat2x4;

typedef struct {
	vec3	row0;
	vec3	row1;
	vec3	row2;
}mat3X3;
typedef mat3X3 mat3;

typedef struct {
	vec2	row0;
	vec2	row1;
	vec2	row2;
}mat3X2;

typedef struct {
	vec2	row0;
	vec2	row1;
	vec2	row2;
	vec2	row3;
}mat4X2;

typedef struct {
	vec3	row0;
	vec3	row1;
	vec3	row2;
	vec3	row3;
}mat4X3;

typedef struct {
	vec4	row0;
	vec4	row1;
	vec4	row2;
}mat3X4;



#define _MAT44F					\
typedef struct {				\
	float32 m00, m01, m02, m03, \
			m10, m11, m12, m13, \
			m20, m21, m22, m23, \
			m30, m31, m32, m33; \
}Mat44f;						
_MAT44F;



typedef struct {
	vec2   min;
	vec2   max;
}S_Bounding2D;



//=============================================== 颜色 ==================================================
typedef struct {
	uint8 r;
	uint8 g;
	uint8 b;
}S_RGB8UI;

typedef struct {
	uint8 r;
	uint8 g;
	uint8 b;
	uint8 a;
}S_RGBA8UI;

inline S_RGBA8UI operator + (const S_RGBA8UI& a, const S_RGBA8UI& b) {
	S_RGBA8UI Color;
	Color.r = DEF_Min(a.r + b.r, 255);
	Color.g = DEF_Min(a.g + b.g, 255);
	Color.b = DEF_Min(a.b + b.b, 255);
	Color.a = DEF_Min(a.a + b.a, 255);
	return Color;
}

inline S_RGBA8UI operator - (const S_RGBA8UI& a, const S_RGBA8UI& b) {
	S_RGBA8UI Color;
	Color.r = DEF_Min(a.r - b.r, 255);
	Color.g = DEF_Min(a.g - b.g, 255);
	Color.b = DEF_Min(a.b - b.b, 255);
	Color.a = DEF_Min(a.a - b.a, 255);
	return Color;
}

inline void operator += (S_RGBA8UI& a, const S_RGBA8UI& b) {
	a.r = DEF_Min(a.r + b.r, 255);
	a.g = DEF_Min(a.g + b.g, 255);
	a.b = DEF_Min(a.b + b.b, 255);
	a.a = DEF_Min(a.a + b.a, 255);
}

inline void operator -= (S_RGBA8UI& a, const S_RGBA8UI& b) {
	a.r = DEF_Max(a.r - b.r, 0);
	a.g = DEF_Max(a.g - b.g, 0);
	a.b = DEF_Max(a.b - b.b, 0);
	a.a = DEF_Max(a.a - b.a, 0);
}




//=================================================== 数组 ===================================================

typedef struct {        
	bool*  ptr_userData; 
	uint32 count;  
}S_BoolArray;	

typedef struct {        
	int8*  ptr_userData; 
	uint32 count;  
}S_I8Array;	

CORE_ARRAY_HANDLE(S_UI8Array, uint8);

typedef struct {			
	float32* ptr_userData;	
	uint32   count;		
}S_F32Array;		

typedef struct {			
	int32*	ptr_userData;	
	uint32	count;		    
}S_I32Array;	

typedef struct {			
	uint32*	ptr_userData;	
	uint32	count;		    
}S_UI32Array;	


//typedef struct {
//	S_UI32Array** ptr_userData;
//	uint32	count;
//}S_UI32Array2D;

typedef struct {			
	vec2*	ptr_userData;	
	uint32	count;			
}S_Vec2Array;

typedef struct {		
	vec3*  ptr_userData;	
	uint32 count;		
}S_Vec3Array;

typedef struct {		
	vec4*  ptr_userData;	
	uint32 count;		
}S_Vec4Array;

typedef struct {			
	ivec2*	ptr_userData;	
	uint32	count;			
}S_iVec2Array;

typedef struct {			
	uvec2*	ptr_userData;	
	uint32	count;			
}S_uVec2Array;

typedef struct {			
	ivec3*	ptr_userData;	
	uint32	count;			
}S_iVec3Array;

typedef struct {			
	mat3X3* ptr_userData;	
	uint32	count;			
}S_Mat33Array;

typedef struct {			
	Mat44f* ptr_userData;	
	uint32	count;			
}S_Mat44Array;






template<typename T1, typename T2>
Inline float32 f_JIT_Fun_f_c_f(T1* v1, T2* v2, uint8 CalType) {
	float32 r;
	switch (CalType) {
	case 0: r = float32(v1[0]) + float32(v2[0]); break;
	case 1: r = float32(v1[0]) - float32(v2[0]); break;
	case 2: r = float32(v1[0]) * float32(v2[0]); break;
	case 3: r = float32(v1[0]) / float32(v2[0]); break;
	case 4: {
		break;
	}
	case 5: {
		break;
	}
	case 6: {

		break;
	}
	case 7: {
		break;
	}
	}
	return r;
}

/*template<typename T1, typename T2>
Inline void f_JIT_Fun_fs_c_fs(float32* r, T1* v1, T2* v2, uint32 size[2], uint8 CalType) {
	uint32 num = size[0];
	bool single = size[1] < num;

	for (uint32 i = 0; i < num; ++i) {
		if (single) {
			switch (CalType) {
			case 0: r[i] = float32(v1[i]) + float32(v2[0]); break;
			case 1: r[i] = float32(v1[i]) - float32(v2[0]); break;
			case 2: r[i] = float32(v1[i]) * float32(v2[0]); break;
			case 3: r[i] = float32(v1[i]) / float32(v2[0]); break;
			
			}
		}
		else {
			switch (CalType) {
			case 0: r[i] = float32(v1[i]) + float32(v2[i]); break;
			case 1: r[i] = float32(v1[i]) - float32(v2[i]); break;
			case 2: r[i] = float32(v1[i]) * float32(v2[i]); break;
			case 3: r[i] = float32(v1[i]) / float32(v2[i]); break;

			}
		}
	}
}*/


template<typename T1>
Inline void f_JIT_Fun_Clamp(float32* r, T1* v1, uint32 num, vec2 range) {
	for (uint32 i = 0; i < num; ++i) {
		r[i] = DEF_Min(DEF_Max(range.x, v1[i]), range.y);
	}
}


//Inline vec3 clamp(vec3 x, vec3 minVal, vec3 maxVal) {
//	return { DEF_Min(DEF_Max(x.x, minVal.x), maxVal.x), DEF_Min(DEF_Max(x.y, minVal.y), maxVal.y), DEF_Min(DEF_Max(x.z, minVal.z), maxVal.z) };
//}


CORE_ARRAY_HANDLE(S_UI32Array2D, S_UI32Array*)
CORE_ARRAY_HANDLE(S_Vec3Array2D, S_Vec3Array*)
CORE_ARRAY_HANDLE(S_iVec3Array2D, S_iVec3Array*)

CORE_ARRAY_HANDLE(S_TexArray, struct S_纹理*)




Inline float sign(float v) {
	return v > 0 ? 1 : (v < 0 ? -1 : 0);
}

Inline int32 sign(int32 v) {
	return v > 0 ? 1 : (v < 0 ? -1 : 0);
}







#endif //INCLUDE_BASIC_VEC


